#ifndef INC_DIAGRAMMAN_H
#define INC_DIAGRAMMAN_H

#include <QObject>
#include <QTabWidget>
#include <boost/shared_ptr.hpp>

class DiagramFam;
class UMLDiagram;
class MouseListener;

class DiagramMan : public QObject
{
	Q_OBJECT;

	typedef boost::shared_ptr<DiagramFam> DiagramFamPtr;
	typedef std::vector<DiagramFamPtr> diagrams_type;

	public:
		DiagramMan(QWidget* canvasParent);

		// Just for debugging.
		~DiagramMan();

		/*** ACCESSORS ***/

		/**
		 * Note about mouseListener: This will typically be a bridge from view
		 * to controller. Controller will be destroyed before View. Therefore,
		 * the Controller must be careful to null this pointer when it's dying.
		 */
		MouseListener* mouseListener();
		void setMouseListener(MouseListener*);

		/**
		 * @return a QWidget used to display canvases
		 */
		QWidget* display();

		/**
		 * @return a DiagramMan-owned pointer to the active DiagramFam, or NULL
		 * if there is none.
		 */
		DiagramFam& active();

		/**
		 * @return true if there is an active DiagramFam.
		 */
		bool isActive() const;

		/**
		 * Add the specified diagram to the manager.
		 *
		 * Note: the man will now own your pointer.
		 */
		void add(UMLDiagram*);

		/**
		 * Loads the diagram from the XML file in path and adds it to the
		 * manager.
		 */
		void add(const QString& path);

	public slots:
		void closeActive();

	signals:
		void activeChanged(DiagramFam* active);

	protected slots:
		void closeTab(int);

	private:

		/* Should this be wrapped in a view class? Right now I say no so that we
		 * have more control, e.g., for storing the current DiagramFam* (which a
		 * view class would have no knowledge of). Basically, the view class
		 * would do nothing but tighten QWidget* to UMLCanvas*. Not a huge
		 * benefit for a lot of effort. Anyway...
		 *
		 * Invariant: all widgets are UMLCanvases. (See addCanvas().)
		 *
		 * WARNING: This is a view class! It must be constructed first and
		 * destructed last!
		 */
		QTabWidget _canvases;

		MouseListener* _ml; // init-checked
		diagrams_type _diagrams;

		DiagramFamPtr _cFam;

		void add(DiagramFamPtr);

		/**
		 * QTabWidget::addTab() wrapper to ensure only UMLCanvases are added.
		 * @return index of added tab
		 */
		int addCanvas(DiagramFam& fam);

		/**
		 * Internal utility function to get the shared_ptr from a tab index.
		 * @return an iterator into _diagrams, or _diagrams.end()
		 */
		diagrams_type::iterator lookupPtr(int);

	private slots:
		void tabChanged(int index);
};

inline bool DiagramMan::isActive() const
{
	return _cFam.get();
}

#endif // INC_DIAGRAMFAM_H

